﻿using System;
using System.IO;
using System.Text;
using System.Linq;
using System.Windows;
using System.Windows.Markup;
using UltimatePlugin.Technicals;
using System.Windows.Controls;
using System.Reflection;

namespace UltimatePlugin.UI
{
    internal class UIManager
    {
        private static Window _ConfigWindow;
        
        public static Window GetDisplayWindow()
        {
            // Check we can actually find the .xaml file first - if not, report an error
            if (!File.Exists(Path.Combine(FileManager.ViewPath, "MainView.xaml")))
            {
                Logger.Write(LogSeverity.Debug, LogCategory.UI, "MainView.xaml not found {0}", Path.Combine(FileManager.ViewPath, "MainView.xaml"));
                return null;
            }
            try
            {
                if (_ConfigWindow != null)
                {
                    return _ConfigWindow;
                }

                _ConfigWindow = new Window()
                    {
                        DataContext = new ConfigViewModel(),
                        Content = LoadFromFile(),
                        Title = "Ultimate Plugin",
                        Height = 520,
                        MinHeight = 520,
                        Width = 480, 
                        MinWidth = 480
                    };
                _ConfigWindow.Closed += WindowClosed;
            }
            catch (XamlParseException ex)
            {
                Logger.Write(LogSeverity.Error, LogCategory.UI, "{0}", ex);
                return _ConfigWindow;
            }
            return _ConfigWindow;
        }

        private static UserControl LoadFromFile()
        {
            UserControl mainControl = LoadAndTransformXamlFile<UserControl>(Path.Combine(FileManager.ViewPath, "MainView.xaml"));
            LoadChild(mainControl, FileManager.ViewPath);
            LoadResourceForWindow(Path.Combine(FileManager.ViewPath, "Template.xaml"), mainControl);
            return mainControl;
        }

        
        /// <summary>Closes the current window.</summary>
        public static void CloseWindow()
        {
            _ConfigWindow.Close();
        }

        /// <summary>Loads the XAML resource file for window.</summary>
        /// <param name="filename">The filename.</param>
        /// <param name="control">The control.</param>
        private static void LoadResourceForWindow(string filename, UserControl control)
        {
            ResourceDictionary resource = LoadAndTransformXamlFile<ResourceDictionary>(filename);
            foreach (System.Collections.DictionaryEntry res in resource)
            {
                control.Resources.Add(res.Key, res.Value);
            }
        }

        /// <summary>Loads the and transform xaml file.</summary>
        /// <param name="filename">The filename to load.</param>
        /// <returns><see cref="Stream"/> which contains transformed XAML file.</returns>
        private static T LoadAndTransformXamlFile<T>(string filename)
        {
            string filecontent = File.ReadAllText(filename);
            // Change reference to custom Trinity class
            filecontent = filecontent.Replace("xmlns:utlimate=\"clr-namespace:UltimatePlugin.UI\"", "xmlns:utlimate=\"clr-namespace:UltimatePlugin.UI;assembly=" + Assembly.GetExecutingAssembly().GetName().Name + "\"");
            // Remove Template designer reference
            filecontent = filecontent.Replace("<ResourceDictionary.MergedDictionaries><ResourceDictionary Source=\"..\\Template.xaml\"/></ResourceDictionary.MergedDictionaries>", string.Empty);
            filecontent = filecontent.Replace("<ResourceDictionary.MergedDictionaries><ResourceDictionary Source=\"Template.xaml\"/></ResourceDictionary.MergedDictionaries>", string.Empty);

            return (T)XamlReader.Load(new MemoryStream(Encoding.Default.GetBytes(filecontent)));
        }

        /// <summary>Call when Config Window is closed.</summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        static void WindowClosed(object sender, System.EventArgs e)
        {
            _ConfigWindow = null;
        }

        /// <summary>Loads recursivly the child in ContentControl or Decorator with Tag.</summary>
        /// <param name="parentControl">The parent control.</param>
        /// <param name="uiPath">The UI path.</param>
        private static void LoadChild(FrameworkElement parentControl, string uiPath)
        {
            // Loop in Children of parent control of type FrameworkElement 
            foreach (FrameworkElement ctrl in LogicalTreeHelper.GetChildren(parentControl).OfType<FrameworkElement>())
            {
                string contentName = ctrl.Tag as string;
                // Tag contains a string end with ".xaml" : It's dymanic content 
                if (!string.IsNullOrWhiteSpace(contentName) && contentName.EndsWith(".xaml"))
                {
                    // Load content from XAML file
                    LoadDynamicContent(uiPath, ctrl, System.IO.Path.Combine(uiPath, contentName));
                }
                else
                {
                    // Try again with children of control
                    LoadChild(ctrl, uiPath);
                }
            }
        }

        /// <summary>Loads the dynamic content from XAML file.</summary>
        /// <param name="uiPath">The UI path.</param>
        /// <param name="ctrl">The CTRL.</param>
        /// <param name="filename">Name of the content.</param>
        private static void LoadDynamicContent(string uiPath, FrameworkElement ctrl, string filename)
        {
            if (File.Exists(filename))
            {
                Logger.Write(LogSeverity.Error, LogCategory.UI, "Error XAML file not found : '{0}'", filename);
                return;
            }

            UserControl xamlContent = LoadAndTransformXamlFile<UserControl>(filename);

            if (ctrl is ContentControl) // Dynamic load of content is possible on Content control (UserControl, ...)
            {
                ((ContentControl)ctrl).Content = xamlContent;
            }
            else if (ctrl is Decorator) // Or on Decorator control (Border, ...)
            {
                ((Decorator)ctrl).Child = xamlContent;
            }

            // Content added to parent control, try to search dynamic control in children
            LoadChild(xamlContent, uiPath);
        }
    }
}
